/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package src.view.loan;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.primefaces.context.RequestContext;
import org.primefaces.event.CloseEvent;
import org.primefaces.event.DateSelectEvent;
import src.domain.customer.Customer;
import src.domain.loan.*;
import src.domain.saving.Saving;
import src.domain.security.Users;
import src.services.customer.CustomerModel;
import src.services.gl.GlaccntModel;
import src.services.loan.*;
import src.services.saving.SavingModel;
import src.util.Constanta;
import src.util.Messager;
import src.util.Utils;
import src.view.security.LoginBean;

/**
 *
 * @author jay
 */
@ManagedBean
@SessionScoped
public class LoanBean implements Serializable {

    private List<SelectItem> avaibleProduct, avaibleCoral, availableGL;
    private List<SelectItem> availableFee, avblMarketing;
    private List<Paypoint> avblPoint;
    private Loancoral selectedData, unsaveCoral;
    private Loancost selectedCost, unsaveCost;
    private Loan loan;
    private LoanprodModel prodHelper;
    private CollateralModel coralHelper;
    private GlaccntModel glHelper;
    private LoanModel helper;
    private String disbAccnt, disbAccntOwner;
    private String autodebitAccnt, autodebitAccntOwner;
    private Integer branchId, colateralId, coralsIdx, feeId, feeIdx, searchSatus=1;
    private boolean editMode = false, editDetailMode=true, insertionMode=false;
    
    private Users users;
    
    private String defaultButton="doNothingLoan";
    private boolean showLookup=false;
    
    public LoanBean() {
        ambilUser();
        this.coralHelper = new CollateralModel();
        this.prodHelper = new LoanprodModel();
        this.glHelper = new GlaccntModel();
        this.helper = new LoanModel();
        newData();
        editMode = false;
    }
    
    private boolean cekConfig() {
        boolean complete=true;
        
        this.branchId = users.getBranch().getBranchId();
                
        if (this.branchId==null) complete=false;
            
        if(complete==false) Messager.showWarning("loanUnconfig");
        
        else {
            //cek laon no
            complete = !helper.isNumberExist(loan.getLoanNo(), loan.getLoanId());
            if(complete==false) Messager.showWarning("loanNoIsExist");
            
            //cek sppk no
            else {
                complete = !helper.isSPKNumberExist(loan.getSpkNo(), loan.getLoanId());
                if(complete==false) Messager.showWarning("sppkNoIsExist");
            }
        }
        
        return complete;
    }

    public boolean isEditMode() {
        return editMode;
    }
        
    public Integer getSearchSatus() {
        return searchSatus;
    }

    public void setSearchSatus(Integer searchSatus) {
        this.searchSatus = searchSatus;
    }
    
    public Loan getLoan() {
        return loan;
    }

    public void setLoan(Loan loan) {
        this.loan = loan;
    }

    public List<SelectItem> getAvaibleProduct() {
        return avaibleProduct;
    }

    public List<SelectItem> getAvaibleCoral() {
        return avaibleCoral;
    }

    public List<SelectItem> getAvailableGL() {
        return availableGL;
    }

    public List<SelectItem> getAvailableFee() {
        return availableFee;
    }

    public List<Paypoint> getAvblPoint() {
        return avblPoint;
    }

    public List<SelectItem> getAvblMarketing() {
        return avblMarketing;
    }

    public Loancost getSelectedCost() {
        return selectedCost;
    }

    public Loancost getUnsaveCost() {
        return unsaveCost;
    }

    public Integer getFeeId() {
        return feeId;
    }

    public void setFeeId(Integer feeId) {
        this.feeId = feeId;
    }
    
    public void setAvailableGL(List<SelectItem> availableGL) {
        this.availableGL = availableGL;
    }

    public Loancoral getSelectedData() {
        return selectedData;
    }

    public void setSelectedData(Loancoral selectedData) {
        this.selectedData = selectedData;
    }

    public Integer getColateralId() {
        return colateralId;
    }

    public void setColateralId(Integer colateralId) {
        this.colateralId = colateralId;
    }
    
    public Loancoral getUnsaveCoral() {
        return unsaveCoral;
    }

    public void setUnsaveCoral(Loancoral unsaveCoral) {
        this.unsaveCoral = unsaveCoral;
    }
    
    public Integer getBranchId() {
        return branchId;
    }
    
    public void handleRemoveDetail() {  
        if (loan.getLoancorals().size() == 1) loan.getLoancorals().add(new Loancoral());
    }
    
    public void handleRemoveCost() {  
        if (loan.getLoancosts().size() == 1) loan.getLoancosts().add(new Loancost());
    }
    
    private void removeEmptyRow(){
        for(int i = 0; i<loan.getLoancorals().size(); i++){
           Integer id = loan.getLoancorals().get(i).getCollateralId();
           if(id==null) {
               loan.getLoancorals().remove(i);
               i--;
           }
        }
    }
     
    private void removeEmptyCost(){
        for(int i = 0; i<loan.getLoancosts().size(); i++){
           Integer id = loan.getLoancosts().get(i).getFeeId();
           if(id==null) {
               loan.getLoancosts().remove(i);
               i--;
           }
        }
    }
    
    public void newDetail() {
        this.unsaveCoral = new Loancoral();
        editDetailMode = false;
        handleCoralChange();
    }
    
    public void newCost() {
        this.unsaveCost = new Loancost();
        editDetailMode = false;
        //handleCostChange();
    }
        
    public void editDetail(Loancoral data) {
        colateralId = data.getCollateralId();
        coralsIdx = loan.getLoancorals().indexOf(data);
        unsaveCoral = Loancoral.clone(data);
        editDetailMode = true;
    }
    
    public void editCost(Loancost data) {
        feeId = data.getFeeId();
        feeIdx = loan.getLoancosts().indexOf(data);
        unsaveCost = Loancost.clone(data);
        editDetailMode = true;
    }
    
    public void saveDetail() {
        boolean success=true;
        try {
            unsaveCoral.setCollateralId(colateralId);
            if(!editDetailMode) {
                this.loan.getLoancorals().add(unsaveCoral);
                removeEmptyRow();
                
            } else this.loan.getLoancorals().set(coralsIdx, Loancoral.clone(unsaveCoral));

        } catch (RuntimeException e) {success=false;
        } finally {Messager.showSaveUpdateStatus(success);}
    }
    
    public void saveCost() {
        boolean success=true;
        try {
            unsaveCost.setFeeId(feeId);
            if(!editDetailMode) {
                this.loan.getLoancosts().add(unsaveCost);
                removeEmptyCost();
                
            } else this.loan.getLoancosts().set(feeIdx, Loancost.clone(unsaveCost));

        } catch (RuntimeException e) {success=false;
        } finally {Messager.showSaveUpdateStatus(success);}
    }
    
    private void initForm() {
        this.avaibleProduct = prodHelper.listAll();
        this.avaibleCoral = coralHelper.listAll();
        this.availableGL = glHelper.listAll();
        this.availableFee = new LoanfeeModel().listAll();
        this.avblPoint = PaypointConverter.paypointDB;
        this.avblMarketing = new MarketingModel().listAll();
                
        this.editMode = true;
        this.showLookup=false;
        this.disbAccnt= null;
        this.disbAccntOwner= null;
        this.autodebitAccnt= null;
        this.autodebitAccntOwner= null;
    }
        
    public final void newData() {  
        initForm();
        if (this.loan!=null) loan = null;
        this.loan = new Loan(true);
        this.loan.getLoancorals().add(new Loancoral());     
        this.loan.getLoancosts().add(new Loancost());     
        this.loan.setBranchId(branchId);
        
        cekConfig();
        
        insertionMode = true;
    }
    
    public void getDisbSaving(String accntNo) {
        if ("null".equals(accntNo)) accntNo = disbAccnt;
        
        boolean found=false;
        if (accntNo!=null ) {
            
            Saving saving = new SavingModel().getByAccount(accntNo);
            if (saving==null) {
                this.loan.setDisbursementSavaccntId(null);
                this.disbAccnt=null;
                this.disbAccntOwner=null;
                Messager.showWarning("accntNotFound");
                
            } else {
                found=true;
                this.loan.setDisbursementSavaccntId(saving.getSavaccntId());
                this.disbAccnt=saving.getAccountNo();
                this.disbAccntOwner=saving.getCustomer().getCustomerName();
            }   
        }
        RequestContext.getCurrentInstance().addCallbackParam("success", found); 
    }
    
    public void getAutodebitSaving(String accntNo) {
        if ("null".equals(accntNo)) accntNo = autodebitAccnt;
        
        boolean found=false;
        if (accntNo!=null ) {
            
            Saving saving = new SavingModel().getByAccount(accntNo);
            if (saving==null) {
                this.loan.setLoanAutodebitSavingId(null);
                this.autodebitAccnt=null;
                this.autodebitAccntOwner=null;
                Messager.showWarning("accntNotFound");
                
            } else {
                found=true;
                this.loan.setLoanAutodebitSavingId(saving.getSavaccntId());
                this.autodebitAccnt=saving.getAccountNo();
                this.autodebitAccntOwner=saving.getCustomer().getCustomerName();
            }   
        }
        RequestContext.getCurrentInstance().addCallbackParam("success", found); 
    }
    
    public Customer getCustomerByCIF(String cif) {
        CustomerModel custHelper = new CustomerModel();
        Customer cust = custHelper.getByCif(cif);
        return cust;
    }
    
    public void getLoanCustomer(String cif) {
        boolean found=false;
        if ("null".equals(cif)) cif = loan.getCustomer().getCif();
        
        if (!cif.equals("") && cif!=null ) {
            Customer customer = getCustomerByCIF(cif);
            if (customer==null) {
                //reset
                this.loan.setCustomer(new Customer());
                Messager.showWarning("customerNotFound");
            }
            
            else {
                found=true;
                this.loan.setCustomer(customer);
            }
        }
        RequestContext.getCurrentInstance().addCallbackParam("success", found); 
    }
    
    public void editData(Integer value) {  
        boolean found=false;
        
        if (value!=null ) {
            found=true;
            insertionMode=false;
            editMode=true;
            loan = helper.getById(value);
            if (loan.getDisbursementSavaccntId() != null) {
                Saving saving = new SavingModel().getById(loan.getDisbursementSavaccntId());
                this.disbAccnt=saving.getAccountNo();
                this.disbAccntOwner=saving.getCustomer().getCustomerName(); 
            }
            
            if (loan.getLoanAutodebitSavingId() != null) {
                Saving saving = new SavingModel().getById(loan.getLoanAutodebitSavingId());
                this.autodebitAccnt=saving.getAccountNo();
                this.autodebitAccntOwner=saving.getCustomer().getCustomerName(); 
            }
        }
        RequestContext.getCurrentInstance().addCallbackParam("success", found);
    }
    
    public void getInterestRate(){  
        Integer prodId = loan.getLoanprod().getLoanprodId();
        BigDecimal amount = loan.getPrincipalAmount();
        
        if(prodId != null && amount != null) {
            BigDecimal intrate = prodHelper.getInterestRate(loan.getLoanprod().getLoanprodId(), loan.getPrincipalAmount());
            loan.setInterestRate(intrate); 
        } else loan.setInterestRate(null); 
    }  
    
    public void handleProdChange() {  
        
        Loanprod produk = new Loanprod();
        Integer id = loan.getLoanprod().getLoanprodId();
        
        if (id != null) {
            produk = prodHelper.getById(id);
            getInterestRate();
        }            
        loan.setLoanprod(produk);
     //   newNumber();
    }  
    
    public String selectItemValueOf(List<SelectItem> avblList, Integer id) {
        return (String) Utils.selectItemValueOf(avblList, id);
    }
    
    private void save() {
        removeEmptyRow();
        removeEmptyCost();

        if (loan.getMarketingId() == -1) loan.setMarketingId(null);
        loan.setLoanStatus(Constanta.LOANSTATUS_WORKSHEET);
        loan.setUserId(users.getUserId());

        loan.setLoancorals(loan.getLoancorals());
        boolean success = helper.saveData(loan);
        
        // re-insert
        if (!success && insertionMode) loan.setLoanId(null);
        else insertionMode = false;
        
        editMode = !success;        
        Messager.showSaveUpdateStatus(success);    
        RequestContext.getCurrentInstance().addCallbackParam("success", success); 
    }
    
    public void trySave() {
        if (cekConfig()==true) save();
    }
    
    public void delete() {
        
        boolean success = helper.saveData(loan);
        editMode = !success;        
        
        if (success) {
            loan = null;
            loan = new Loan();
        }
        
        Messager.showDeleteStatus(success);     
    }
    
    public void handleCoralChange() {  
        List<CoralAttrib> obj = new LoanCoralAttribModel().findAll(colateralId);
        List<LoanCoralAttrib> lcoralAttribs = new ArrayList<>();
        
        for (int i=0; i<obj.size(); i++) 
            lcoralAttribs.add(new LoanCoralAttrib(obj.get(i)));
        
        unsaveCoral.setLoanCoralAtrribs(Loancoral.cloneAtrib(lcoralAttribs));
    }
    
    public String getDefaultButton() {
        return defaultButton;
    }

    public void setDefaultButton(String defaultButton) {
        this.defaultButton = defaultButton;
    }

    public boolean isShowLookup() {
        return showLookup;
    }

    public void setShowLookup(boolean showLookup) {
        this.showLookup = showLookup;
    }

   
    
    public String getDisbAccnt() {
        return disbAccnt;
    }

    public void setDisbAccnt(String disbAccnt) {
        this.disbAccnt = disbAccnt;
    }

    public String getDisbAccntOwner() {
        return disbAccntOwner;
    }

    public String getAutodebitAccnt() {
        return autodebitAccnt;
    }

    public void setAutodebitAccnt(String autodebitAccnt) {
        this.autodebitAccnt = autodebitAccnt;
    }

    public String getAutodebitAccntOwner() {
        return autodebitAccntOwner;
    }

    public void setAutodebitAccntOwner(String autodebitAccntOwner) {
        this.autodebitAccntOwner = autodebitAccntOwner;
    }
        
    public void handleCloseLookup(CloseEvent event) {
        this.showLookup=false;
    }
    
    public void handleDisbDateSelect(DateSelectEvent event) {  
        loan.setDisbursementDate(event.getDate());
        handlePeriod();
    }
    
    public void handleDueDateSelect(DateSelectEvent event) {  
        loan.setDueDate(event.getDate());
    }
  
    public void handlePeriod() {  
         if (loan.getPeriod() != null)
         loan.setDueDate(new LoansimulateModel().setMoth(loan.getDisbursementDate(), loan.getPeriod()));
    }
    
    public void calcFeeAmount() {
        BigDecimal amt = loan.getPrincipalAmount();
        BigDecimal pct = unsaveCost.getFeePc().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_DOWN);
                
        if (amt != null || pct != null) 
            unsaveCost.setFeeAmount(amt.multiply(pct)); 
    }
    
    public void calcFeepc() {
        BigDecimal amt = loan.getPrincipalAmount();
        BigDecimal feeAmt = unsaveCost.getFeeAmount();
        if (amt != null || feeAmt != null) {
            BigDecimal tmp = feeAmt.divide(amt, new MathContext(3));
            unsaveCost.setFeePc(tmp.multiply(BigDecimal.valueOf(100)));
        }
    }
    
    private void ambilUser() {
        FacesContext context = FacesContext.getCurrentInstance();
        LoginBean logBean = (LoginBean) context.getApplication().evaluateExpressionGet(context, "#{loginBean}", LoginBean.class);
        this.users = logBean.getSelectedUser();
    }
 
    public void showDialog(String value) {
        value+=".show();";
        RequestContext.getCurrentInstance().execute(value);
    }
}
